/*
 * Menu: ActionScript > PureMVC > Project Generator 
 * Kudos: Lance Woodson
 * DOM: http://localhost/org.eclipse.eclipsemonkey.lang.javascript
 */
var flexDirTree = {
		controller: {},
		events: {},
		model: {
			vo: {}
		},
		view: {
			component: {}
		},
		junction: {}
};
var assetsDirTree = {
	assets: {
		actionscript: {},
		css: {},
		images: {},
		swf: {}
	}
};
var applicationSuffix = "App";
var moduleSuffix = "Module";
var projectTitle = null;
var facadeDirName = "blah";

var groupIdPath;
var baseDirFile;
var appDir;
var appFileName = "application.mxml";
var appFile;
var facadeDir;
var facadeFileName = "ApplicationFacade.as";
var facadeFile;
var facadeContent = "test";
var appType;

function main() {	
	queryForBaseDir();
	queryForAppType();
	queryForProjectTitle();
	parseGroupIdPath();	
	createDirectoryStructure();
	buildMainAppMXML();
	buildFacade();
}

function queryForAppType() {
	appType = gatherInput("Specify project type", "What type of project do you want to generate, APPLICATION or MODULE (default MODULE)?", "MODULE");
}

function queryForProjectTitle() {
	var input = gatherInput("Specify project title", "What project identifier would you like to use in the package structure?", projectTitle);
	if (input == "") {
		input = projectTitle;
	}
	projectTitle = input;
}

function buildFacade() {
	facadeContent = "package com.me.myapp\n" +
				   "{\n" +
				   "\timport org.puremvc.as3.multicore.patterns.facade.Facade;\n" + 
				   "\n" +
				   "\tpublic class ApplicationFacade extends Facade\n" +
				   "\t{\n" +
				   '\t\tpublic static const STARTUP:String = "STARTUP";\n' +
				   '\t\tpublic static const SHUTDOWN:String = "SHUTDOWN";\n\n' +
				   "\t\tpublic static function getInstance(key:String):ApplicationFacade\n" +
				   "\t\t\tif (instanceMap[key] == null) \n" +
				   "\t\t\t\t\tinstanceMap[key] = new ApplicationFacade(key);\n" +
				   "\t\t\treturn instanceMap[key] as ApplicationFacade;\n" +
				   "\t\t}\n\n" +
				   "\t\toverride protected function initializeController():void\n" +
				   "\t\t{\n" +
				   "\t\t\tsuper.initializeController();\n" +
				   "\t\t\t// TODO register commands by mapping command classes to notification names\n" +
				   "\t\t}\n\n" +
				   "\t\tpublic function startup(app:Application):void\n" +
				   "\t\t{\n" +
				   "\t\t\tsendNotification(STARTUP, app);\n" +
				   "\t\t}\n\n" +
				   "\t\tpublic function shutdown(app:Application):void\n" +
				   "\t\t{\n" +
				   "\t\t\tsendNotification(SHUTDOWN, app);\n" +
				   "\t\t}\n" +
				   "\t}\n" +
				   "}";

	var file = Packages.java.io.File(facadeDir, facadeFileName);
	if (file.createNewFile()) {
		out.println("Created " + file.getAbsolutePath());
	} else {
		out.println(file.getAbsolutePath() + " already exists.");
	}
	writeFileContents(file, facadeContent);
}

function buildMainAppMXML() {
	var importStatement = '\t\t\timport ' +  groupIdPath + '.' + projectTitle + '.ApplicationFacade;\n\n';
	var separator = Packages.java.io.File.separator;
	if (separator == '\\') {
		separator = '\\\\';
	}
	var regex = new RegExp(separator, "g");
	importStatement = importStatement.replace(regex, '.');
	var appHeader = '<?xml version="1.0" encoding="utf-8"?>\n' +
	  				'<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"\n' +
	  				'                width="100%"\n' +
	  				'                height="100%"\n' +
	  				'                creationComplete="facade.startup(this)"\n' +
	  				'>\n';
	var appFooter = '</mx:Application>';
	var moduleHeader = '<cp:PipeAwareModule xmlns:mx="http://www.adobe.com/2006/mxml"\n' +
	                   '                    xmlns:cp="com.crengland.flex.commons.puremvc.pipes.*"\n' +
	                   '                    layout="absolute"\n' + 
	                   '                    width="100%"\n' +
	                   '                    height="100%"\n' +
	                   '                    creationComplete="facade.startup(this)"\n' +
	                   '                    implements="org.puremvc.as3.multicore.utilities.pipes.interfaces.IPipeAware">\n';
	var moduleFooter = '</cp:PipeAwareModule>';
	
	var body = '\t<mx:Script>\n' +
	              '\t\t<![CDATA[\n' +
	              importStatement +
	              '\t\t\tprivate var facade:ApplicationFacade = ApplicationFacade.getInstance("WorkflowApplicatonFacade");\n' +
	              '\t\t]]>\n' +
	          	  '\t</mx:Script>\n' +
				  '\t<!-- TODO implement content -->\n'
	          	  
	var content;
	if (appType == "APPLICATION") {
		content = appHeader + body + appFooter;
		appFileName = projectTitle.capitalized() + applicationSuffix + ".mxml";
	} else {
		appFileName = projectTitle.capitalized() + moduleSuffix + ".mxml";
		content = moduleHeader + body + moduleFooter;
	}
	var file = new Packages.java.io.File(appDir, appFileName);
	if (file.createNewFile()) {
		out.println("Created " + file.getAbsolutePath());
	} else {
		out.println(file.getAbsolutePath() + " already exists.");
	}
	writeFileContents(file, content);
}

function writeFileContents(file, content) {
	var writer = new Packages.java.io.PrintWriter(new Packages.java.io.BufferedWriter(new Packages.java.io.FileWriter(file)));
	for (var i = 0; i < content.length; i++) {
		writer.print(content.charAt(i));
	}
	writer.close();
	out.println("Wrote contents of " + file.getAbsolutePath());
}

function createDirectoryStructure() {
	function buildDirs(dirFile, dirStructure) {
		for(var dirName in dirStructure) {			
			var dir = new Packages.java.io.File(dirFile, dirName);
			
			if (dir.mkdir()) {
				out.println("Creating directory " + dir.getAbsolutePath());
			} else {
				out.println("Directory " + dir.getAbsolutePath() + " already exists.");
			}
			
			// debug(dir.getName() + ": " + facadeDirName);
			/*
			if (dir.getName() == facadeDirName) {
				facadeDir = dir;
				out.println(facadeFileName + " to be created in " + facadeDir.getAbsolutePath());
			}
			*/
			buildDirs(dir, dirStructure[dirName]);
		}
	}
	
	var baseFlexDir = new Packages.java.io.File(
			baseDirFile, 
			groupIdPath + Packages.java.io.File.separator + projectTitle);
	if (baseFlexDir.mkdirs()) {
		out.println("Creating directory " + baseFlexDir.getAbsolutePath());
	} else {
		out.println(baseFlexDir.getAbsolutePath() + " already exists.");
	}
	
	facadeDir = baseFlexDir;
	appDir = baseDirFile;
	
	buildDirs(baseFlexDir, flexDirTree);
	buildDirs(baseDirFile, assetsDirTree);
}

function parseGroupIdPath() {
	var pomFile = null;
	function pomFetcher(f) {
		var files = f.listFiles();
		for (var i = 0; i < files.length; i++) {
			if (files[i].getName() == "pom.xml") {
				pomFile = files[i];
				return;
			}
		}
		pomFetcher(f.getParentFile());
	}
	
	pomFetcher(baseDirFile);
	if (!pomFile) {
		throw "Unable to find pom for project."
	}
	
	var groupId = null;
	var parentRegex = new RegExp("parent");
	var groupIdRegex = new RegExp("groupId>(.+)<");
	var artifactIdRegex = new RegExp("artifactId>(.+)<");
	var content = readFile(pomFile);
	var contentLines = content.split('\n');
	var inParentStanza = false;
	for (var i = 0; i < contentLines.length; i++) {
		if (parentRegex.exec(contentLines[i])) {			
			inParentStanza = !inParentStanza;
		} else if (!inParentStanza) {
			var comparisonResult = groupIdRegex.exec(contentLines[i]);
			if (comparisonResult && !groupId) {
				groupId = comparisonResult[1];
			}
			if (!projectTitle) {
				comparisonResult = artifactIdRegex.exec(contentLines[i]);
				if (comparisonResult) {
					projectTitle = comparisonResult[1];
					out.println("parsed artifact ID: " + projectTitle);
				}
			}
		}	
	}
	if (!groupId) {
		throw "Unable to parse group ID from " + pomFile.getAbsolutePath();
	}

	groupIdPath = groupId.replace(/\./g, Packages.java.io.File.separator);
	out.println("Parsed group id path: " + groupIdPath);
	var typeDir = "app";
	if (appType != "APPLICATION") {
		typeDir = "module";		
	}
	groupIdPath = groupIdPath + Packages.java.io.File.separator + typeDir;
}

function queryForBaseDir() {
	var dialog = new Packages.org.eclipse.ui.dialogs.ElementTreeSelectionDialog(
			window.getShell(),
			new Packages.org.eclipse.ui.model.WorkbenchLabelProvider(), 
			new Packages.org.eclipse.ui.model.BaseWorkbenchContentProvider()
	);
	dialog.setTitle("Flex Source Directory Selection");
	dialog.setMessage("Select a flex source directory to serve as a base for the project generation");
	dialog.setInput(Packages.org.eclipse.core.resources.ResourcesPlugin.getWorkspace().getRoot());
	dialog.open();
	var selection = dialog.getResult()[0];
	baseDirFile = new Packages.java.io.File(selection.getLocationURI());
	out.println("Building pure mvc project structure in " + baseDirFile.getAbsolutePath());
}

function queryToPopulate(dataObject) {
	for(var property in dataObject) {
		dataObject[property] = gatherInput("Define Variables", "Enter a value for " + property, null);
	}
	return dataObject;
}

function gatherInput(label, queryString, defaultValue) {
	dialog = new Packages.org.eclipse.jface.dialogs.InputDialog(
	          window.getShell(), 
	          label,
	          queryString,
	          null, null
	);
	result = dialog.open()
	// if (result == Packages.org.eclipse.jface.window.Window.OK)
		return dialog.getValue();
}

function readFile(file) {
	var reader = new Packages.java.io.BufferedReader(new Packages.java.io.FileReader(file));
	var content = "";
	var text;
	while ((text = reader.readLine()) != null) {
		content = content + text + "\n"; 
	}
	reader.close();
	return content;
}
	
function debug(s) {
	Packages.org.eclipse.jface.dialogs.MessageDialog.openInformation(window.getShell(), "Monkey Debugging", s);
}

String.prototype.capitalized = function(){
	return this.substring(0, 1).toUpperCase() + this.slice(1).toLowerCase();
};